home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume20 / deliver2.0 / part04 < prev    next >
Encoding:
Internet Message Format  |  1989-10-15  |  36.9 KB

  1. Subject:  v20i026:  Deliver, flexible email delivery system, Part04/04
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Chip Salzenberg <chip@ateng.com>
  7. Posting-number: Volume 20, Issue 26
  8. Archive-name: deliver2.0/part04
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of shell archive."
  17. # Contents:  mbox.c procs.c subs.c sysdep.c unctime.y uucp.c
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. if test -f 'mbox.c' -a "${1}" != "-c" ; then 
  20.   echo shar: Will not clobber existing file \"'mbox.c'\"
  21. else
  22. echo shar: Extracting \"'mbox.c'\" \(4366 characters\)
  23. sed "s/^X//" >'mbox.c' <<'END_OF_FILE'
  24. X/* $Header: mbox.c,v 2.1 89/06/09 12:25:33 network Exp $
  25. X *
  26. X * Finally!  Put the message in the specified mailbox(es).
  27. X *
  28. X * $Log:    mbox.c,v $
  29. X * Revision 2.1  89/06/09  12:25:33  network
  30. X * Update RCS revisions.
  31. X * 
  32. X * Revision 1.6  89/06/09  12:23:55  network
  33. X * Baseline for 2.0 release.
  34. X * 
  35. X */
  36. X
  37. X#include "deliver.h"
  38. X#include <sys/stat.h>
  39. X#include <errno.h>
  40. X
  41. X/*
  42. X * External data.
  43. X */
  44. X
  45. Xextern  int     errno;
  46. X
  47. X/*
  48. X * Local functions.
  49. X */
  50. X
  51. Xstatic          mbox_one();
  52. Xstatic  int     mbox_write();
  53. X
  54. X/*----------------------------------------------------------------------
  55. X * Deliver mail to all valid destinations.
  56. X */
  57. X
  58. Xmbox_deliver()
  59. X{
  60. X    DEST    *d;
  61. X
  62. X    for (d = first_dest(); d; d = next_dest(d))
  63. X    {
  64. X        switch (d->d_class)
  65. X        {
  66. X        case CL_USER:
  67. X        case CL_MBOX:
  68. X            if (d->d_state == ST_WORKING)
  69. X                mbox_one(d);
  70. X            break;
  71. X        }
  72. X    }
  73. X}
  74. X
  75. X/*----------------------------------------------------------------------
  76. X * Deliver mail to one destination.
  77. X */
  78. X
  79. Xstatic
  80. Xmbox_one(d)
  81. XDEST    *d;
  82. X{
  83. X    CONTEXT *ct;
  84. X    int     ret = 0;
  85. X
  86. X    if (printaddrs)
  87. X    {
  88. X        (void) printf("%s", d->d_name);
  89. X        if (d->d_class == CL_MBOX)
  90. X            (void) printf(":%s", d->d_mailbox);
  91. X        (void) printf("\n");
  92. X    }
  93. X
  94. X    if (dryrun)
  95. X    {
  96. X        d->d_state = ST_DONE;
  97. X        return;
  98. X    }
  99. X
  100. X    if ((ct = name_context(d->d_name)) == NULL)
  101. X    {
  102. X        dest_err(d, E_CTLOST);
  103. X        return;
  104. X    }
  105. X
  106. X    if (! ok_context(ct))
  107. X    {
  108. X        dest_err(d, E_CTPERM);
  109. X        return;
  110. X    }
  111. X
  112. X    if (d->d_class == CL_MBOX)
  113. X    {
  114. X        if (sfork() == 0)
  115. X        {
  116. X            if (become(ct, !boxdelivery) < 0)
  117. X                exit(1);
  118. X            if (mbox_write(d->d_mailbox, ct, FALSE) < 0)
  119. X                exit(1);
  120. X            exit(0);
  121. X        }
  122. X
  123. X        if (await_child() != 0)
  124. X            ret = -1;
  125. X    }
  126. X    else
  127. X    {
  128. X        char    mailbox[100];
  129. X
  130. X        (void) sprintf(mailbox, "%s/%s",
  131. X#ifdef MBX_DIR
  132. X            MBX_DIR, d->d_name
  133. X#else
  134. X            d->d_home, MBX_NAME
  135. X#endif
  136. X            );
  137. X
  138. X        if (mbox_write(mailbox, ct, TRUE) < 0)
  139. X            ret = -1;
  140. X    }
  141. X
  142. X    if (ret >= 0)
  143. X        d->d_state = ST_DONE;
  144. X    else
  145. X        dest_err(d, E_MBOX);
  146. X}
  147. X
  148. X/*----------------------------------------------------------------------
  149. X * Write mail to the named mailbox.
  150. X * If we have to create the mailbox, give it to the specified user.
  151. X * If "is_sys" is true, then we're writing to a system mailbox.
  152. X */
  153. X
  154. Xstatic int
  155. Xmbox_write(mailbox, ct, is_sys)
  156. Xchar    *mailbox;
  157. XCONTEXT *ct;
  158. Xint     is_sys;
  159. X{
  160. X    struct stat st;
  161. X    int     fd, t, mbox_uid, mbox_gid;
  162. X    int     ret = 0;
  163. X
  164. X    if (verbose)
  165. X    {
  166. X        message("As %s, delivering to %s mailbox %s\n",
  167. X            ct->ct_name, (is_sys ? "system" : "user"), mailbox);
  168. X    }
  169. X
  170. X    if (name_lock(mailbox) < 0)
  171. X        return -1;
  172. X
  173. X    while ((fd = open(mailbox, O_WRONLY)) == -1)
  174. X    {
  175. X        if (errno != ENOENT)
  176. X        {
  177. X            syserr("can't open %s", mailbox);
  178. X            break;
  179. X        }
  180. X
  181. X#ifdef O_CREAT
  182. X        fd = open(mailbox, O_WRONLY|O_CREAT|O_EXCL, MBX_MODE);
  183. X
  184. X        /* If it exists now, try open() again. */
  185. X        if (fd == -1 && errno == EEXIST)
  186. X            continue;
  187. X#else
  188. X        fd = creat(mailbox, MBX_MODE);
  189. X#endif
  190. X        if (fd == -1)
  191. X        {
  192. X            syserr("can't create %s", mailbox);
  193. X            break;
  194. X        }
  195. X
  196. X        /* Make sure the mailbox receives the correct modes */
  197. X
  198. X        mbox_uid = ct->ct_uid;
  199. X        mbox_gid = ct->ct_gid;
  200. X
  201. X#ifdef MBX_GROUP
  202. X        if (is_sys)
  203. X        {
  204. X            static int mbox_sv_gid = -2;
  205. X
  206. X            if (mbox_sv_gid == -2)
  207. X                mbox_sv_gid = group_id(MBX_GROUP);
  208. X
  209. X            if (mbox_sv_gid < 0)
  210. X                message("%s: no such group\n", MBX_GROUP);
  211. X            else
  212. X                mbox_gid = mbox_sv_gid;
  213. X        }
  214. X#endif /* MBX_GROUP */
  215. X
  216. X        if (fstat(fd, &st) == -1)
  217. X        {
  218. X            syserr("can't fstat open mailbox?!");
  219. X            (void) close(fd);
  220. X            fd = -1;
  221. X            break;
  222. X        }
  223. X
  224. X        /* Change mailbox ownership if it's not already correct. */
  225. X
  226. X        if ((st.st_uid != mbox_uid || st.st_gid != mbox_gid)
  227. X         && chown(mailbox, mbox_uid, mbox_gid) == -1)
  228. X        {
  229. X            /* print a message, but that's all. (???) */
  230. X            syserr("can't chown %s to %d,%d",
  231. X                mailbox, mbox_uid, mbox_gid);
  232. X        }
  233. X
  234. X        /* It's open now, so we can stop looping now. */
  235. X
  236. X        break;
  237. X    }
  238. X
  239. X    if (fd == -1)
  240. X    {
  241. X        (void) name_unlock(mailbox);
  242. X        return -1;
  243. X    }
  244. X
  245. X    if (fd_lock(fd) < 0)
  246. X    {
  247. X        (void) close(fd);
  248. X        (void) name_unlock(mailbox);
  249. X        return -1;
  250. X    }
  251. X
  252. X    (void) lseek(fd, 0L, 2); /* No error check: may be a special file */
  253. X
  254. X    for (t = T_HDR; t <= T_BODY; ++t)
  255. X    {
  256. X        if (lseek(tfd[t], 0L, 0) == -1)
  257. X        {
  258. X            syserr("lseek in %s file %s", ttype[t], tfile[t]);
  259. X            ret = -1;
  260. X            break;
  261. X        }
  262. X
  263. X        if (copyfd(tfd[t], fd) < 0)
  264. X        {
  265. X            ret = -1;
  266. X            break;
  267. X        }
  268. X    }
  269. X
  270. X    if (verbose)
  271. X    {
  272. X        if (ret >= 0)
  273. X            message("wrote message to %s\n", mailbox);
  274. X    }
  275. X
  276. X    if (fd_unlock(fd) < 0)
  277. X        ret = -1;
  278. X    (void) close(fd);
  279. X    if (name_unlock(mailbox) < 0)
  280. X        ret = -1;
  281. X
  282. X    return ret;
  283. X}
  284. END_OF_FILE
  285. if test 4366 -ne `wc -c <'mbox.c'`; then
  286.     echo shar: \"'mbox.c'\" unpacked with wrong size!
  287. fi
  288. # end of 'mbox.c'
  289. fi
  290. if test -f 'procs.c' -a "${1}" != "-c" ; then 
  291.   echo shar: Will not clobber existing file \"'procs.c'\"
  292. else
  293. echo shar: Extracting \"'procs.c'\" \(5039 characters\)
  294. sed "s/^X//" >'procs.c' <<'END_OF_FILE'
  295. X/* $Header: procs.c,v 2.1 89/06/09 12:25:37 network Exp $
  296. X *
  297. X * Process management and misc support.
  298. X *
  299. X * $Log:    procs.c,v $
  300. X * Revision 2.1  89/06/09  12:25:37  network
  301. X * Update RCS revisions.
  302. X * 
  303. X * Revision 1.5  89/06/09  12:23:57  network
  304. X * Baseline for 2.0 release.
  305. X * 
  306. X */
  307. X
  308. X#include "deliver.h"
  309. X#include <errno.h>
  310. X#include <signal.h>
  311. X
  312. X/*
  313. X * External data.
  314. X */
  315. X
  316. Xextern  int     errno;
  317. X
  318. X/*
  319. X * Local data.
  320. X */
  321. X
  322. Xstatic  int     child_pid = -1;
  323. Xstatic  SIGTYPE (*saved_sigpipe)() = SIG_DFL;
  324. X
  325. X/*----------------------------------------------------------------------
  326. X * Like popen(), but execute the child in a specific context.
  327. X * Also, the argument list is already a vector.
  328. X */
  329. X
  330. XFILE *
  331. Xct_popenv(ct, prog, av, mode)
  332. XCONTEXT *ct;
  333. Xchar    *prog;
  334. Xchar    **av;
  335. Xchar    *mode;
  336. X{
  337. X    char    ch;
  338. X    int     child, parent;
  339. X    int     pfd[2];
  340. X
  341. X    if (!ct || !prog || !av || !mode)
  342. X        return NULL;
  343. X
  344. X    if (mode[0] == 'r' && mode[1] == 0)
  345. X        child = 1, parent = 0;
  346. X    else if (mode[0] == 'w' && mode[1] == 0)
  347. X        child = 0, parent = 1;
  348. X    else
  349. X        return NULL;
  350. X
  351. X    /* We can't have more than one child at a time. */
  352. X
  353. X    if (child_pid >= 0)
  354. X    {
  355. X        error("in ct_popen: a process is already open\n");
  356. X        return NULL;
  357. X    }
  358. X
  359. X    /* Make a stab at predicting uid-related failure. */
  360. X
  361. X    if (! ok_context(ct))
  362. X    {
  363. X        error("in ct_popen: no permissions to become %s\n",
  364. X              ct->ct_name);
  365. X        return NULL;
  366. X    }
  367. X
  368. X    /* Pipes?  Like, tubular, fer shur! */
  369. X
  370. X    if (pipe(pfd) == -1)
  371. X    {
  372. X        syserr("can't create a pipe");
  373. X        return NULL;
  374. X    }
  375. X
  376. X    /* Generate a debugging message. */
  377. X
  378. X    if (verbose)
  379. X    {
  380. X        int a;
  381. X
  382. X        message("Spawning");
  383. X        for (a = 0; av[a]; ++a)
  384. X            message(" %s", av[a]);
  385. X        message("\n");
  386. X    }
  387. X
  388. X    /* Handle the child case */
  389. X
  390. X    if (sfork() == 0)
  391. X    {
  392. X        if (child == 0)
  393. X        {
  394. X            (void) close(0);
  395. X            (void) dup(pfd[0]);     /* ass_u_me 0 */
  396. X        }
  397. X        else
  398. X        {
  399. X            (void) close(0);
  400. X            if (open("/dev/null", O_RDONLY) != 0)
  401. X            {
  402. X                /* This should _never_ happen, but... */
  403. X                syserr("can't open /dev/null");
  404. X                (void) dup(1);  /* ass_u_me 0 */
  405. X            }
  406. X
  407. X            (void) close(1);
  408. X            (void) dup(pfd[1]);     /* ass_u_me 1 */
  409. X        }
  410. X
  411. X        if (become(ct, TRUE) < 0)
  412. X            (void) write(pfd[1], "n", 1);
  413. X        else
  414. X        {
  415. X            int     t;
  416. X
  417. X            (void) write(pfd[1], "y", 1);
  418. X
  419. X            (void) close(pfd[child]);
  420. X            (void) close(pfd[parent]);
  421. X            for (t = 0; t < T_MAX; ++t)
  422. X                (void) close(tfd[t]);
  423. X
  424. X            (void) execv(prog, av);
  425. X            syserr("can't execute %s", prog);
  426. X        }
  427. X
  428. X        exit(127);
  429. X    }
  430. X
  431. X    /* Make sure that a broken pipe won't kill us */
  432. X
  433. X    saved_sigpipe = signal(SIGPIPE, SIG_IGN);
  434. X
  435. X    /* The child must report "OK" before we continue. */
  436. X
  437. X    if ((read(pfd[0], &ch, 1) < 1) || (ch != 'y'))
  438. X    {
  439. X        (void) close(pfd[0]);
  440. X        (void) close(pfd[1]);
  441. X        (void) await_child();
  442. X        return NULL;
  443. X    }
  444. X
  445. X    (void) close(pfd[child]);
  446. X    return fdopen(pfd[parent], mode);
  447. X}
  448. X
  449. X/*----------------------------------------------------------------------
  450. X * Close the stream opened by ct_popen().
  451. X */
  452. X
  453. Xct_pclose(fp)
  454. XFILE    *fp;
  455. X{
  456. X    if (fp)
  457. X        (void) fclose(fp);
  458. X    return await_child();
  459. X}
  460. X
  461. X/*----------------------------------------------------------------------
  462. X * Assume the identity of the given user.
  463. X */
  464. X
  465. Xint
  466. Xbecome(ct, chd)
  467. XCONTEXT *ct;
  468. Xint     chd;
  469. X{
  470. X    char    env_path[32];
  471. X
  472. X    /*
  473. X     * Assume a new identity.
  474. X     * Note the importance of doing the setgid() before the setuid().
  475. X     */
  476. X
  477. X    if (setgid(ct->ct_gid) == -1)
  478. X    {
  479. X        syserr("can't setgid to %d", ct->ct_gid);
  480. X        return -1;
  481. X    }
  482. X    if (setuid(ct->ct_uid) == -1)
  483. X    {
  484. X        syserr("can't setgid to %u", ct->ct_uid);
  485. X        return -1;
  486. X    }
  487. X    if (chd && chdir(ct->ct_home) == -1)
  488. X    {
  489. X        syserr("can't chdir to %s", ct->ct_home);
  490. X        return -1;
  491. X    }
  492. X
  493. X    /* Set up the environment */
  494. X
  495. X    (void) sprintf(env_path, "%s:/bin:/usr/bin",
  496. X            ((ct->ct_uid == 0) ? "/etc" : "."));
  497. X    alloc_env("HOME", ct->ct_home);
  498. X    alloc_env("PATH", env_path);
  499. X
  500. X    /* I guess it worked. */
  501. X
  502. X    return 0;
  503. X}
  504. X
  505. X/*----------------------------------------------------------------------
  506. X * Safe fork.  If it doesn't work, it exits.
  507. X */
  508. X
  509. Xint
  510. Xsfork()
  511. X{
  512. X    int     tries;
  513. X
  514. X    /*
  515. X     * A few safety measures.
  516. X     */
  517. X
  518. X    (void) await_child();
  519. X    (void) fflush(stdout);
  520. X    (void) fflush(stderr);
  521. X
  522. X    /*
  523. X     * Be patient in waiting for a fork().
  524. X     */
  525. X
  526. X    for (tries = 0; tries < 10; ++tries)
  527. X    {
  528. X        if (tries)
  529. X            snooze(3);
  530. X        if ((child_pid = fork()) >= 0)
  531. X            return child_pid;
  532. X        if (errno != EAGAIN)
  533. X            break;
  534. X    }
  535. X
  536. X    syserr("can't fork");
  537. X    leave(1);
  538. X    /* NOTREACHED */
  539. X}
  540. X
  541. X/*----------------------------------------------------------------------
  542. X * Wait for our child (if any) to exit.
  543. X * Returns child's exit status or -1 if there is a problem.
  544. X */
  545. X
  546. Xint
  547. Xawait_child()
  548. X{
  549. X    int     wpid, st;
  550. X
  551. X    if (child_pid < 0)
  552. X        return -1;
  553. X
  554. X    while ((wpid = wait(&st)) >= 0)
  555. X    {
  556. X        if (wpid == child_pid)
  557. X            break;
  558. X    }
  559. X
  560. X    child_pid = -1;
  561. X    if (wpid == -1)
  562. X        syserr("waiting for child");
  563. X
  564. X    (void) signal(SIGPIPE, saved_sigpipe);
  565. X    saved_sigpipe = SIG_DFL;
  566. X
  567. X    if (wpid == -1)
  568. X        return -1;
  569. X
  570. X    if (st & 0xFF)
  571. X    {
  572. X        error("child process died%s due to signal %d.\n",
  573. X            ((st & 0x80) ? " and dumped core" : ""),
  574. X            (st & 0x7F));
  575. X
  576. X        return -1;
  577. X    }
  578. X
  579. X    if (verbose)
  580. X    {
  581. X        message("child process exited with status %d.\n",
  582. X            (st >> 8) & 0xFF);
  583. X    }
  584. X
  585. X    return ((st >> 8) & 0xFF);
  586. X}
  587. END_OF_FILE
  588. if test 5039 -ne `wc -c <'procs.c'`; then
  589.     echo shar: \"'procs.c'\" unpacked with wrong size!
  590. fi
  591. # end of 'procs.c'
  592. fi
  593. if test -f 'subs.c' -a "${1}" != "-c" ; then 
  594.   echo shar: Will not clobber existing file \"'subs.c'\"
  595. else
  596. echo shar: Extracting \"'subs.c'\" \(2650 characters\)
  597. sed "s/^X//" >'subs.c' <<'END_OF_FILE'
  598. X/* $Header: subs.c,v 2.1 89/06/09 12:25:39 network Exp $
  599. X *
  600. X * Miscellaneous subroutines.
  601. X *
  602. X * $Log:    subs.c,v $
  603. X * Revision 2.1  89/06/09  12:25:39  network
  604. X * Update RCS revisions.
  605. X * 
  606. X * Revision 1.8  89/06/09  12:23:58  network
  607. X * Baseline for 2.0 release.
  608. X * 
  609. X */
  610. X
  611. X#include "deliver.h"
  612. X
  613. X/*----------------------------------------------------------------------
  614. X * Allocate memory for an environment variable, and putenv() it.
  615. X */
  616. X
  617. Xalloc_env(name, value)
  618. Xchar    *name;
  619. Xchar    *value;
  620. X{
  621. X    char    *s;
  622. X
  623. X    if (!name || !value)
  624. X        return;
  625. X
  626. X    s = zalloc((unsigned) (strlen(name) + strlen(value) + 2));
  627. X    (void) sprintf(s, "%s=%s", name, value);
  628. X    if (putenv(s))
  629. X        nomem();
  630. X}
  631. X
  632. X/*----------------------------------------------------------------------
  633. X * Remove an environment variable.
  634. X */
  635. X
  636. Xdel_env(name)
  637. Xchar    *name;
  638. X{
  639. X    int     len;
  640. X    char    **e;
  641. X
  642. X    if (!name)
  643. X        return;
  644. X
  645. X    len = strlen(name);
  646. X
  647. X    for (e = environ; *e; ++e)
  648. X    {
  649. X        char    c;
  650. X
  651. X        if (strncmp(*e, name, len) != 0)
  652. X            continue;
  653. X
  654. X        c = (*e)[len];
  655. X        if (c == '=' || c == '\0')
  656. X            break;
  657. X    }
  658. X
  659. X    for (; *e; ++e)
  660. X        *e = *(e + 1);
  661. X}
  662. X
  663. X/*----------------------------------------------------------------------
  664. X * Allocate and clear.  If it fails, it takes the emergency exit.
  665. X */
  666. X
  667. Xchar *
  668. Xzalloc(size)
  669. Xunsigned size;
  670. X{
  671. X    char    *p;
  672. X
  673. X    if ((p = malloc(size)) == NULL)
  674. X        nomem();
  675. X
  676. X    Zero(p, size);
  677. X    return p;
  678. X}
  679. X
  680. X/*----------------------------------------------------------------------
  681. X * Reallocate to new size.  If it fails, it takes the emergency exit.
  682. X */
  683. X
  684. Xchar *
  685. Xsrealloc(ptr, size)
  686. Xchar    *ptr;
  687. Xunsigned size;
  688. X{
  689. X    char    *p;
  690. X
  691. X    if ((p = realloc(ptr, size)) == NULL)
  692. X        nomem();
  693. X
  694. X    return p;
  695. X}
  696. X
  697. X/*----------------------------------------------------------------------
  698. X * Make an allocated copy of a string.
  699. X */
  700. X
  701. Xchar *
  702. Xcopystr(s)
  703. Xchar    *s;
  704. X{
  705. X    char    *p;
  706. X
  707. X    if (s == NULL)
  708. X        return NULL;
  709. X
  710. X    if ((p = malloc((unsigned) strlen(s) + 1)) == NULL)
  711. X        nomem();
  712. X
  713. X    (void) strcpy(p, s);
  714. X    return p;
  715. X}
  716. X
  717. X/*----------------------------------------------------------------------
  718. X * Emergency exit for memory loss.
  719. X */
  720. X
  721. Xnomem()
  722. X{
  723. X    error("out of memory\n");
  724. X    leave(1);
  725. X}
  726. X
  727. X/*----------------------------------------------------------------------
  728. X * Return the last component of the given pathname.
  729. X */
  730. X
  731. Xchar *
  732. Xbasename(name)
  733. Xchar    *name;
  734. X{
  735. X    char    *b;
  736. X
  737. X    if ((b = strrchr(name, '/')) != NULL)
  738. X        ++b;
  739. X    else
  740. X        b = name;
  741. X
  742. X    return (b);
  743. X}
  744. X
  745. X/*----------------------------------------------------------------------
  746. X * Check an address for validity.
  747. X */
  748. X
  749. Xvalid_address(addr)
  750. Xchar    *addr;
  751. X{
  752. X    char    *p;
  753. X    static char sanitize[] = SANITIZE;
  754. X
  755. X    for (p = addr; *p; ++p)
  756. X    {
  757. X        if (strchr(sanitize, *p))
  758. X            return FALSE;
  759. X    }
  760. X
  761. X    return TRUE;
  762. X}
  763. END_OF_FILE
  764. if test 2650 -ne `wc -c <'subs.c'`; then
  765.     echo shar: \"'subs.c'\" unpacked with wrong size!
  766. fi
  767. # end of 'subs.c'
  768. fi
  769. if test -f 'sysdep.c' -a "${1}" != "-c" ; then 
  770.   echo shar: Will not clobber existing file \"'sysdep.c'\"
  771. else
  772. echo shar: Extracting \"'sysdep.c'\" \(6647 characters\)
  773. sed "s/^X//" >'sysdep.c' <<'END_OF_FILE'
  774. X/* $Header: sysdep.c,v 2.1 89/06/09 12:25:40 network Exp $
  775. X *
  776. X * Routines which are (or might well be) system-dependant.
  777. X * I've put the message routines here since you may need to use
  778. X * the ANSI <stdarg.h> instead of <varargs.h>.
  779. X *
  780. X * $Log:    sysdep.c,v $
  781. X * Revision 2.1  89/06/09  12:25:40  network
  782. X * Update RCS revisions.
  783. X * 
  784. X * Revision 1.8  89/06/09  12:23:59  network
  785. X * Baseline for 2.0 release.
  786. X * 
  787. X */
  788. X
  789. X#include "deliver.h"
  790. X#include <errno.h>
  791. X#ifdef HAS_STDARG
  792. X#include <stdarg.h>
  793. X#else
  794. X#ifdef HAS_VARARGS
  795. X#include <varargs.h>
  796. X#else
  797. X/*
  798. X * Non-portable home-grown varargs.  Use at your own risk.
  799. X * Especially note that if sizeof(int) > sizeof(short), then
  800. X * "va_arg(..,short)" is broken.
  801. X */
  802. Xtypedef char *va_list;
  803. X#define va_dcl          int va_alist;
  804. X#define va_start(ap)    ap = (char *) &va_alist
  805. X#define va_arg(ap,type) *(type *)(ap += sizeof(type), ap - sizeof(type))
  806. X#define va_end(ap)      /* nothing */
  807. X#endif
  808. X#endif
  809. X
  810. X#ifdef UNAME
  811. X#include <sys/utsname.h>
  812. X#endif
  813. X
  814. X/*
  815. X * External functions.
  816. X */
  817. X
  818. X#ifdef M_XENIX
  819. Xextern  long    nap();
  820. X#else
  821. Xextern  unsigned sleep();
  822. X#endif
  823. X
  824. X/*
  825. X * External data.
  826. X */
  827. X
  828. Xextern  int     errno;
  829. Xextern  int     sys_nerr;
  830. Xextern  char    *sys_errlist[];
  831. X
  832. X/*----------------------------------------------------------------------
  833. X * Print a message.
  834. X */
  835. X
  836. X/* VARARGS */
  837. X#ifdef HAS_STDARG
  838. Xmessage(char *fmt, ...)
  839. X#else
  840. Xmessage(va_alist) va_dcl
  841. X#endif
  842. X{
  843. X    va_list ap;
  844. X
  845. X#ifdef HAS_STDARG
  846. X    va_start(ap, fmt);
  847. X#else
  848. X    char    *fmt;
  849. X    va_start(ap);
  850. X    fmt = va_arg(ap, char *);
  851. X#endif
  852. X
  853. X    (void) vfprintf(stderr, fmt, ap);
  854. X
  855. X    va_end(ap);
  856. X}
  857. X
  858. X/*----------------------------------------------------------------------
  859. X * Print an error message.
  860. X */
  861. X
  862. X/* VARARGS */
  863. X#ifdef HAS_STDARG
  864. Xerror(char *fmt, ...)
  865. X#else
  866. Xerror(va_alist) va_dcl
  867. X#endif
  868. X{
  869. X    va_list ap;
  870. X
  871. X#ifdef HAS_STDARG
  872. X    va_start(ap, fmt);
  873. X#else
  874. X    char    *fmt;
  875. X    va_start(ap);
  876. X    fmt = va_arg(ap, char *);
  877. X#endif
  878. X
  879. X    (void) fprintf(stderr, "%s: ", progname);
  880. X    (void) vfprintf(stderr, fmt, ap);
  881. X
  882. X    va_end(ap);
  883. X}
  884. X
  885. X/*----------------------------------------------------------------------
  886. X * Report an error returned from a system call.
  887. X */
  888. X
  889. X/* VARARGS */
  890. X#ifdef HAS_STDARG
  891. Xsyserr(char *fmt, ...)
  892. X#else
  893. Xsyserr(va_alist) va_dcl
  894. X#endif
  895. X{
  896. X    int     e = errno;
  897. X    va_list ap;
  898. X
  899. X#ifdef HAS_STDARG
  900. X    va_start(ap, fmt);
  901. X#else
  902. X    char    *fmt;
  903. X    va_start(ap);
  904. X    fmt = va_arg(ap, char *);
  905. X#endif
  906. X
  907. X    (void) fprintf(stderr, "%s: ", progname);
  908. X    (void) vfprintf(stderr, fmt, ap);
  909. X    if (e <= sys_nerr)
  910. X        (void) fprintf(stderr, ": %s\n", sys_errlist[e]);
  911. X    else
  912. X        (void) fprintf(stderr, ": unknown system error %d\n", e);
  913. X
  914. X    va_end(ap);
  915. X}
  916. X
  917. X/*----------------------------------------------------------------------
  918. X * Sleep for the given number of seconds.
  919. X */
  920. X
  921. Xsnooze(n)
  922. Xint     n;
  923. X{
  924. X#ifdef M_XENIX
  925. X    (void) nap(n * 1000L);
  926. X#else
  927. X    (void) sleep(n);
  928. X#endif
  929. X}
  930. X
  931. X/*----------------------------------------------------------------------
  932. X * Get the host name from HOSTFILE.
  933. X */
  934. X
  935. X#ifdef HOSTFILE
  936. X
  937. Xchar *
  938. Xgethost()
  939. X{
  940. X    int     fd, rd;
  941. X    char    *p;
  942. X    static char name[32];
  943. X
  944. X    if ((fd = open(HOSTFILE, O_RDONLY)) == -1)
  945. X        return NULL;
  946. X    rd = read(fd, name, sizeof(name) - 1);
  947. X    (void) close(fd);
  948. X
  949. X    if (rd < 1)
  950. X        return NULL;
  951. X    name[rd] = 0;
  952. X    if ((p = strchr(name, '\n')) != NULL)
  953. X        *p = 0;
  954. X
  955. X    return (name[0] ? name : NULL);
  956. X}
  957. X
  958. X#endif /* HOSTFILE */
  959. X
  960. X/*----------------------------------------------------------------------
  961. X * Get the host name via the uname() system call.
  962. X */
  963. X
  964. X#ifdef UNAME
  965. X
  966. Xchar *
  967. Xgethost()
  968. X{
  969. X    static struct utsname u;
  970. X
  971. X    uname(&u);
  972. X    return (u.nodename[0] ? u.nodename : NULL);
  973. X}
  974. X
  975. X#endif /* UNAME */
  976. X
  977. X/*----------------------------------------------------------------------
  978. X * Get the host name via the gethostname() system call.
  979. X */
  980. X
  981. X#ifdef GETHOSTNAME
  982. X
  983. Xchar *
  984. Xgethost()
  985. X{
  986. X    static char hostname[64];
  987. X
  988. X    if (gethostname(hostname, sizeof(hostname)) == -1)
  989. X        return NULL;
  990. X
  991. X    return hostname;
  992. X}
  993. X
  994. X#endif /* GETHOSTNAME */
  995. X
  996. X/*----------------------------------------------------------------------
  997. X * Return a pre-defined HOSTNAME.
  998. X */
  999. X
  1000. X#ifdef HOSTNAME
  1001. X
  1002. Xchar *
  1003. Xgethost()
  1004. X{
  1005. X    return HOSTNAME;
  1006. X}
  1007. X
  1008. X#endif /* HOSTNAME */
  1009. X
  1010. X/*----------------------------------------------------------------------
  1011. X * Variable-argument-list output, System V style.
  1012. X */
  1013. X
  1014. X#ifndef HAS_VPRINTF
  1015. X
  1016. Xvprintf(fmt, ap)
  1017. Xchar    *fmt;
  1018. Xva_list ap;
  1019. X{
  1020. X    int     a,b,c,d,e,f,g,h;
  1021. X
  1022. X    a = va_arg(ap, int);
  1023. X    b = va_arg(ap, int);
  1024. X    c = va_arg(ap, int);
  1025. X    d = va_arg(ap, int);
  1026. X    e = va_arg(ap, int);
  1027. X    f = va_arg(ap, int);
  1028. X    g = va_arg(ap, int);
  1029. X    h = va_arg(ap, int);
  1030. X
  1031. X    (void) printf(fmt, a,b,c,d,e,f,g,h);
  1032. X}
  1033. X
  1034. Xvfprintf(fp, fmt, ap)
  1035. XFILE    *fp;
  1036. Xchar    *fmt;
  1037. Xva_list ap;
  1038. X{
  1039. X    int     a,b,c,d,e,f,g,h;
  1040. X
  1041. X    a = va_arg(ap, int);
  1042. X    b = va_arg(ap, int);
  1043. X    c = va_arg(ap, int);
  1044. X    d = va_arg(ap, int);
  1045. X    e = va_arg(ap, int);
  1046. X    f = va_arg(ap, int);
  1047. X    g = va_arg(ap, int);
  1048. X    h = va_arg(ap, int);
  1049. X
  1050. X    (void) fprintf(fp, fmt, a,b,c,d,e,f,g,h);
  1051. X}
  1052. X
  1053. Xvsprintf(s, fmt, ap)
  1054. Xchar    *s;
  1055. Xchar    *fmt;
  1056. Xva_list ap;
  1057. X{
  1058. X    int     a,b,c,d,e,f,g,h;
  1059. X
  1060. X    a = va_arg(ap, int);
  1061. X    b = va_arg(ap, int);
  1062. X    c = va_arg(ap, int);
  1063. X    d = va_arg(ap, int);
  1064. X    e = va_arg(ap, int);
  1065. X    f = va_arg(ap, int);
  1066. X    g = va_arg(ap, int);
  1067. X    h = va_arg(ap, int);
  1068. X
  1069. X    (void) sprintf(s, fmt, a,b,c,d,e,f,g,h);
  1070. X}
  1071. X
  1072. X#endif  /* !HAS_VPRINTF */
  1073. X
  1074. X/*----------------------------------------------------------------------
  1075. X * Add a new environment variable.
  1076. X */
  1077. X
  1078. X#ifndef HAS_PUTENV
  1079. X
  1080. Xint
  1081. Xputenv(s)
  1082. Xchar *s;
  1083. X{
  1084. X    static  char    **env_array;
  1085. X    static  int     env_size;
  1086. X    char    *e;
  1087. X    int     i, j;
  1088. X
  1089. X    if (env_array == NULL)
  1090. X    {
  1091. X        for (i = 0; environ[i]; ++i)
  1092. X            {}
  1093. X        env_size = i + 10;      /* arbitrary */
  1094. X        env_array = (char **) zalloc(env_size * sizeof(char *));
  1095. X        Copy((char *)env_array, (char *)environ,
  1096. X             (int) ((i + 1) * sizeof(char *)));
  1097. X        environ = env_array;
  1098. X    }
  1099. X    else if (environ != env_array)
  1100. X        message("putenv: warning: someone moved environ!\n");
  1101. X
  1102. X    if ((e = strchr(s, '=')) != NULL)
  1103. X        ++e;
  1104. X    else
  1105. X        e = s + strlen(s);
  1106. X
  1107. X    j = 0;
  1108. X    for (i = 0; env_array[i]; ++i)
  1109. X    {
  1110. X        if (strncmp(env_array[i], s, e - s) != 0)
  1111. X            env_array[j++] = env_array[i];
  1112. X    }
  1113. X
  1114. X    if ((j + 1) >= env_size)
  1115. X    {
  1116. X        env_size += 10;                 /* arbitrary */
  1117. X        env_array = (char **) srealloc((char *)env_array,
  1118. X                    env_size * sizeof(char **));
  1119. X    }
  1120. X
  1121. X    env_array[j++] = s;
  1122. X    env_array[j] = NULL;
  1123. X
  1124. X    environ = env_array;
  1125. X    return 0;
  1126. X}
  1127. X
  1128. X#endif  /* !HAS_PUTENV */
  1129. X
  1130. X/*----------------------------------------------------------------------
  1131. X * Memory copy.
  1132. X */
  1133. X
  1134. X#ifdef MEMFUNCS
  1135. X
  1136. XCopy(dest, src, len)
  1137. Xchar    *dest;
  1138. Xchar    *src;
  1139. Xint     len;
  1140. X{
  1141. X    while (len-- > 0)
  1142. X        *dest++ = *src++;
  1143. X}
  1144. X
  1145. X#endif
  1146. X
  1147. X/*----------------------------------------------------------------------
  1148. X * Memory clear.
  1149. X */
  1150. X
  1151. X#ifdef MEMFUNCS
  1152. X
  1153. XZero(dest, len)
  1154. Xchar    *dest;
  1155. Xint     len;
  1156. X{
  1157. X    while (len-- > 0)
  1158. X        *dest++ = 0;
  1159. X}
  1160. X
  1161. X#endif
  1162. END_OF_FILE
  1163. if test 6647 -ne `wc -c <'sysdep.c'`; then
  1164.     echo shar: \"'sysdep.c'\" unpacked with wrong size!
  1165. fi
  1166. # end of 'sysdep.c'
  1167. fi
  1168. if test -f 'unctime.y' -a "${1}" != "-c" ; then 
  1169.   echo shar: Will not clobber existing file \"'unctime.y'\"
  1170. else
  1171. echo shar: Extracting \"'unctime.y'\" \(11397 characters\)
  1172. sed "s/^X//" >'unctime.y' <<'END_OF_FILE'
  1173. X/*
  1174. X * $Header: unctime.y,v 2.1 89/06/09 12:25:42 network Exp $
  1175. X *
  1176. X * Conversion of ctime-style date string back to a time_t.
  1177. X * This module is in a different style from the rest of deliver
  1178. X * because Chip Salzenberg didn't write it.
  1179. X *
  1180. X * $Log:    unctime.y,v $
  1181. X * Revision 2.1  89/06/09  12:25:42  network
  1182. X * Update RCS revisions.
  1183. X * 
  1184. X * Revision 1.3  89/06/09  12:24:01  network
  1185. X * Baseline for 2.0 release.
  1186. X * 
  1187. X */
  1188. X
  1189. X/* time_t
  1190. X   unctime(s)
  1191. X      char *s;
  1192. X
  1193. XConvert s, which may be in almost any reasonable date format, to
  1194. Xa time_t integer suitable for consumption by ctime(3).  Coincidentally
  1195. Xdestroys the contents of s.  Return -1 if s is not a recognizable legal date.
  1196. X
  1197. XAny parts of the time left unspecified take on the current values.
  1198. X
  1199. X"4 CST + 23[:10]" adds 23 minutes and optionally 10 seconds to the correction.
  1200. X"# nnnnnn" forces exactly nnnnnn seconds GMT since Jan. 1, 1970.
  1201. X  
  1202. XCopyright 1988, Michael J. Haertel.  Use this routine at your own risk.
  1203. XYou may redistribute verbatim copies of this file.  You may redistribute
  1204. Xmodified versions of this file so long as (1) you state who last changed
  1205. Xit, and (2) this copyright notice appears unmodified.
  1206. X
  1207. XSome debugging by W. Anthony Smith.
  1208. X
  1209. XBug fix, minor enhancements, and non-BSD modifications by David MacKenzie.
  1210. X
  1211. XSeveral changes by Chip Salzenberg for use with deliver:
  1212. X    Include "deliver.h".
  1213. X    Handle military timezones as per RFC822.
  1214. X    Elimination of "#if FTIME" in favor of "#if !USG".
  1215. X    Don't modify input string.
  1216. X    Consider extra junk in date string an error.
  1217. X*/
  1218. X
  1219. X%{
  1220. X#include "deliver.h"
  1221. X#include <ctype.h>
  1222. X#ifdef BSD
  1223. X# include <sys/time.h>
  1224. X#else
  1225. X# include <time.h>
  1226. X# ifndef USG
  1227. X#  include <sys/timeb.h>
  1228. X# endif
  1229. X#endif
  1230. X
  1231. Xextern long atol();
  1232. X
  1233. X/* Delta is correction to turn specified time into GMT. */
  1234. X/* if (zoneflag), a timezone was explicitly specified. */
  1235. Xstatic year, month, day, hour, minute, second, delta, zoneflag, errorflag, iflag;
  1236. Xstatic long iresult;
  1237. X
  1238. X#define YYSTYPE long
  1239. X%}
  1240. X
  1241. X%token NUM MONTH AM PM
  1242. X
  1243. X%%
  1244. X
  1245. Xdate:
  1246. X  day time year
  1247. X  | day year time
  1248. X  | time day year
  1249. X  | time day
  1250. X  | day time
  1251. X  | day year
  1252. X  | day
  1253. X  | time
  1254. X  | '#' NUM        { iflag = TRUE; iresult = $2; }
  1255. X  ;            /* previous line forces exact time in seconds GMT */
  1256. X
  1257. Xday:
  1258. X  NUM MONTH        { month = $2; day = $1; }
  1259. X  | MONTH NUM        { month = $1; day = $2; }
  1260. X  | NUM '/' NUM        { month = $1; day = $3; }
  1261. X  ;
  1262. X
  1263. Xyear:
  1264. X  ',' NUM        { year = $2; }
  1265. X  | '/' NUM        { year = $2; }
  1266. X  | NUM            { year = $1; }
  1267. X  ;
  1268. X
  1269. Xtime:
  1270. X  clock AM        { hour %= 12; }
  1271. X  | clock PM        { hour = hour % 12 + 12; }
  1272. X  | clock
  1273. X  ;
  1274. X
  1275. Xclock:
  1276. X  NUM ':' NUM ':' NUM    { hour = $1; minute = $3; second = $5; }
  1277. X  | NUM ':' NUM        { hour = $1; minute = $3; }
  1278. X  ;
  1279. X
  1280. X%%
  1281. X
  1282. X/* Return true if s is a prefix of t; e.g. prefix("mar", "march") = true.
  1283. X   Note that comparison is case-insensitive. */
  1284. Xstatic
  1285. Xprefix(s,t)
  1286. X     char *s, *t;
  1287. X{
  1288. X  while (*s && *t && tolower(*s) == tolower(*t))
  1289. X    s++, t++;
  1290. X  return *s == 0;
  1291. X}
  1292. X
  1293. Xstatic char *lexptr;
  1294. X
  1295. Xstatic void
  1296. Xinitlex(s)
  1297. X     char *s;
  1298. X{
  1299. X  lexptr = s;
  1300. X}
  1301. X
  1302. Xstatic char *
  1303. Xmonths[] =
  1304. X{
  1305. X  "jan",
  1306. X  "feb",
  1307. X  "mar",
  1308. X  "apr",
  1309. X  "may",
  1310. X  "jun",
  1311. X  "jul",
  1312. X  "aug",
  1313. X  "sep",
  1314. X  "oct",
  1315. X  "nov",
  1316. X  "dec",
  1317. X  0
  1318. X};
  1319. X
  1320. Xstruct zonename
  1321. X{
  1322. X  char *name;            /* Name of the time zone. */
  1323. X  int delta;            /* Correction to add to GMT (in minutes) */
  1324. X};
  1325. X
  1326. Xstatic struct zonename zones[] =
  1327. X{
  1328. X  "gmt", 0,
  1329. X  "ut",  0,
  1330. X  "est", -5 * 60,       /* North American time zones */
  1331. X  "edt", -6 * 60,
  1332. X  "cst", -6 * 60,
  1333. X  "cdt", -7 * 60,
  1334. X  "mst", -7 * 60,
  1335. X  "mdt", -8 * 60,
  1336. X  "pst", -8 * 60,
  1337. X  "pdt", -9 * 60,
  1338. X  "z",   0,             /* Military time zones */
  1339. X  "a",   -1 * 60,
  1340. X  "b",   -2 * 60,
  1341. X  "c",   -3 * 60,
  1342. X  "d",   -4 * 60,
  1343. X  "e",   -5 * 60,
  1344. X  "f",   -6 * 60,
  1345. X  "g",   -7 * 60,
  1346. X  "h",   -8 * 60,
  1347. X  "i",   -9 * 60,
  1348. X  "k",   -10 * 60,
  1349. X  "l",   -11 * 60,
  1350. X  "m",   -12 * 60,
  1351. X  "n",   1 * 60,
  1352. X  "o",   2 * 60,
  1353. X  "p",   3 * 60,
  1354. X  "q",   4 * 60,
  1355. X  "r",   5 * 60,
  1356. X  "s",   6 * 60,
  1357. X  "t",   7 * 60,
  1358. X  "u",   8 * 60,
  1359. X  "v",   9 * 60,
  1360. X  "w",   10 * 60,
  1361. X  "x",   11 * 60,
  1362. X  "y",   12 * 60,
  1363. X  0, 0
  1364. X};
  1365. X
  1366. X/* Lexical analyzer.  Gather alphabetics into tokens; if they are unknown
  1367. X   strings ignore them, and if they are months return the appropriate value.
  1368. X   If the token is the name of the time zone set delta = correction and
  1369. X   zoneflag = TRUE, and skip ahead to the next token (the parser itself
  1370. X   never sees time zones).
  1371. X   If the token is a number, return its value.
  1372. X   If it is a punctuation mark, return the character code.
  1373. X   Ignore white space.  */
  1374. Xstatic
  1375. Xyylex()
  1376. X{
  1377. X  register i;
  1378. X  char token[40];    /* Probably paranoid. */
  1379. X  
  1380. X  for (;;)
  1381. X    {
  1382. X      while (isspace(*lexptr))
  1383. X    lexptr++;
  1384. X      if (*lexptr == 0)
  1385. X    return 0;
  1386. X      else if (isalpha(*lexptr))
  1387. X    {
  1388. X      i = 0;
  1389. X      while (isalpha(*lexptr))
  1390. X        token[i++] = *lexptr++;    /* Null termination is automatic. */
  1391. X      for (i = 0; months[i]; i++)
  1392. X        if (prefix(months[i],token))
  1393. X          {
  1394. X        yylval = i + 1;
  1395. X        return MONTH;
  1396. X          }
  1397. X      for (i = 0; zones[i].name; i++)
  1398. X        if (prefix(zones[i].name,token))
  1399. X          {
  1400. X        int oper, next;
  1401. X
  1402. X        zoneflag = TRUE;
  1403. X        delta = zones[i].delta;
  1404. X        oper = yylex();
  1405. X        /* Syntax: "4 CST + 23[:10]" adds 23 minutes and
  1406. X        optionally 10 seconds to delta (the correction). */
  1407. X        if (oper == '+' || oper == '-')
  1408. X          {
  1409. X            (void) yylex();
  1410. X            delta += (oper == '+' ? 60 : -60) * yylval;
  1411. X            next = yylex();
  1412. X            if (next == ':')
  1413. X              {
  1414. X            (void) yylex();
  1415. X            delta += (oper == '+' ? 1 : -1) * yylval;
  1416. X              }
  1417. X            else
  1418. X              return next;
  1419. X          }
  1420. X        else
  1421. X          return oper;
  1422. X          }
  1423. X      if (prefix("pm",token) || prefix("p.m.", token))
  1424. X        return PM;
  1425. X      if (prefix("am",token) || prefix("a.m.", token))
  1426. X        return AM;
  1427. X      continue;
  1428. X    }
  1429. X      else if (isdigit(*lexptr))
  1430. X    {
  1431. X      i = 0;
  1432. X      while (isdigit(*lexptr))
  1433. X        token[i++] = *lexptr++;
  1434. X      token[i] = '\0';
  1435. X      yylval = atoi(token);
  1436. X      return NUM;
  1437. X    }
  1438. X      else
  1439. X    return *lexptr++;
  1440. X    }
  1441. X}
  1442. X
  1443. X/* ARGSUSED */
  1444. Xstatic
  1445. Xyyerror(s)
  1446. X     char *s;
  1447. X{
  1448. X  errorflag = TRUE;
  1449. X}
  1450. X
  1451. X/* Is y a leap year? */
  1452. X#define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
  1453. X
  1454. X/* Number of leap years from 1970 to y (not including y itself) */
  1455. X#define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
  1456. X
  1457. X/* This macro returns the "day" number of the sunday immediately
  1458. X   preceding or equal to the argument in the current year. */
  1459. X#define FIRST_SUNDAY 3
  1460. X#define dayofepoch(day) ((day) + (year - 1970) * 365 + nleap(year))
  1461. X#define sunday(day)  ((day) - (dayofepoch(day) + 7 - FIRST_SUNDAY) % 7)
  1462. X
  1463. X/* correction()
  1464. X   returns the daylight savings correction in seconds to ADD to GMT
  1465. X   to get correct local time.
  1466. X   Since we are converting local back to GMT, we SUBTRACT this later on
  1467. X   (local = gmt + correction(); gmt = local - correction()).
  1468. X
  1469. X   While we're at it, we also add the longitude correction for minutes
  1470. X   west of Greenwich.  To do this, we have all these fascinating tables
  1471. X   here . . .  */
  1472. X
  1473. X#ifdef BSD
  1474. X
  1475. Xstruct dstinfo
  1476. X{
  1477. X  int year;            /* Info is for this year, or default if zero. */
  1478. X  int start;            /* DST begins sunday before this day. */
  1479. X  int end;            /* DST ends sunday before this day. */
  1480. X};
  1481. X
  1482. X/* USA. */
  1483. Xstatic struct dstinfo
  1484. Xusa_dst[] =
  1485. X{
  1486. X  1974, 5, 333,
  1487. X  1975, 58, 303,
  1488. X  0, 119, 303
  1489. X};
  1490. X
  1491. X/* Australia. */
  1492. Xstatic struct dstinfo
  1493. Xaus_dst[] =
  1494. X{
  1495. X  1970, 999, 0,
  1496. X  1971, 303, 0,
  1497. X  1972, 303, 58,
  1498. X  0, 303, 65
  1499. X};
  1500. X
  1501. X/* Western Europe. */
  1502. Xstatic struct dstinfo
  1503. Xweur_dst[] =
  1504. X{
  1505. X  1983, 89, 296,
  1506. X  0, 89, 303
  1507. X};
  1508. X
  1509. X/* Middle Europe (also used for Eastern Europe, for lack of better
  1510. X   information). */
  1511. Xstatic struct dstinfo
  1512. Xmeur_dst[] =
  1513. X{
  1514. X  1983, 89, 296,
  1515. X  0, 89, 272
  1516. X};
  1517. X
  1518. X/* Canada is same as US, except no early 70's insanity. */
  1519. Xstatic struct dstinfo
  1520. Xcan_dst[] =
  1521. X{
  1522. X  0, 119, 303
  1523. X};
  1524. X
  1525. Xstruct dst_rules
  1526. X{
  1527. X  int magic;            /* Gettimeofday magic number for rule type */
  1528. X  struct dstinfo *entry;    /* Pointer to struct dstinfo array. */
  1529. X  int correction;        /* Correction in minutes to GMT. */
  1530. X};
  1531. X
  1532. Xstatic struct dst_rules
  1533. Xdstrules[] =
  1534. X{
  1535. X  DST_USA, usa_dst, 60,
  1536. X  DST_AUST, aus_dst, -60,    /* Southern hemisphere */
  1537. X  DST_WET, weur_dst, 60,
  1538. X  DST_MET, meur_dst, 60,
  1539. X  DST_EET, meur_dst, 60,
  1540. X  DST_CAN, can_dst, 60,
  1541. X  -1, 0, 0
  1542. X};
  1543. X
  1544. Xstatic
  1545. Xcorrection(day,tz)
  1546. X     int day;                /* Day number in current year.  */
  1547. X     struct timezone *tz;
  1548. X{
  1549. X  int i, correc = 0;
  1550. X  struct dstinfo *dst;
  1551. X  
  1552. X  /* Did the user specify in the input string a timezone correction to use? */
  1553. X  if (zoneflag)
  1554. X    return delta * 60;
  1555. X
  1556. X  /* Since no correction was explicitly specified, we use local time zone and
  1557. X     DST, as returned by gettimeofday() earlier . . . */
  1558. X  if (tz->tz_dsttime)
  1559. X    for (i = 0; dstrules[i].magic != -1; i++)
  1560. X      if (dstrules[i].magic == tz->tz_dsttime)
  1561. X    {
  1562. X      dst = dstrules[i].entry;
  1563. X      while (dst->year != year && dst->year)
  1564. X        dst++;
  1565. X      if (sunday(dst->start) <= day && day <= sunday(dst->end)
  1566. X          /* For some reason, DST starts/ends at 2 am sunday mornings. */
  1567. X          && !(day == sunday(dst->start) && hour < 2)
  1568. X          && !(day == sunday(dst->end) && hour >= 2))
  1569. X        correc = dstrules[i].correction;
  1570. X      break;
  1571. X    }
  1572. X  correc -= tz->tz_minuteswest;
  1573. X  return correc * 60;
  1574. X}
  1575. X
  1576. X#else /* !BSD */
  1577. X
  1578. Xstatic
  1579. Xcorrection()
  1580. X{
  1581. X#ifdef USG
  1582. X  extern long timezone;
  1583. X#else
  1584. X  struct timeb tb;
  1585. X#endif
  1586. X  
  1587. X  /* Did the user specify in the input string a timezone correction to use? */
  1588. X  if (zoneflag)
  1589. X    return delta * 60;
  1590. X
  1591. X  /* Since no correction was explicitly specified, we use local time zone. */
  1592. X#ifdef USG
  1593. X  tzset();
  1594. X  return (int) -timezone;
  1595. X#else
  1596. X  ftime(&tb);
  1597. X  return tb.timezone * -60;
  1598. X#endif
  1599. X}
  1600. X
  1601. X#endif /* !BSD */
  1602. X
  1603. Xstatic short
  1604. Xmonthlens[] =
  1605. X{
  1606. X  31,                /* January */
  1607. X  28,                /* February */
  1608. X  31,                /* March */
  1609. X  30,                /* April */
  1610. X  31,                /* May */
  1611. X  30,                /* June */
  1612. X  31,                /* July */
  1613. X  31,                /* August */
  1614. X  30,                /* September */
  1615. X  31,                /* October */
  1616. X  30,                /* November */
  1617. X  31                /* December */
  1618. X};
  1619. X
  1620. Xtime_t
  1621. Xunctime(s)
  1622. X     char *s;
  1623. X{
  1624. X#ifdef BSD
  1625. X  struct timeval tv;
  1626. X  struct timezone tz;
  1627. X#else
  1628. X  time_t now;
  1629. X#endif
  1630. X  struct tm *tm;
  1631. X  int dayofyear;
  1632. X
  1633. X#ifdef BSD
  1634. X  (void) gettimeofday(&tv,&tz);
  1635. X  /* The cast is required to shut lint up.  Berkeley goes to all the effort
  1636. X     to define time_t, why don't they use it? */
  1637. X  tm = localtime(&(time_t) tv.tv_sec);
  1638. X#else
  1639. X  (void) time(&now);
  1640. X  tm = localtime(&now);
  1641. X#endif
  1642. X  year = tm->tm_year;
  1643. X  month = tm->tm_mon + 1;
  1644. X  day = tm->tm_mday;
  1645. X  hour = tm->tm_hour;
  1646. X  minute = tm->tm_min;
  1647. X  second = tm->tm_sec;
  1648. X  zoneflag = FALSE;
  1649. X  errorflag = FALSE;
  1650. X
  1651. X  initlex(s);
  1652. X  (void) yyparse();
  1653. X
  1654. X  if (errorflag)
  1655. X    return -1;
  1656. X
  1657. X  /* If garbage beyond valid date, that's an error. */
  1658. X  while (*lexptr && isspace(*lexptr))
  1659. X    ++lexptr;
  1660. X  if (*lexptr)
  1661. X     return -1;
  1662. X
  1663. X  /* User forced the exact time in seconds GMT, no further work necessary. */
  1664. X  if (iflag)
  1665. X    return iresult;
  1666. X
  1667. X  /* Try to keep the year reasonable (i.e., within the domain of ctime()). */
  1668. X  if (year < 1970)
  1669. X    year += 1900;
  1670. X  if (year < 1970)
  1671. X    year += 100;
  1672. X
  1673. X  /* Check for preposterous months/days/times. */
  1674. X  if (month < 1 || month > 12 || day < 1 ||
  1675. X      day > monthlens[month - 1] && !(month == 2 && day == 29 && leap(year))
  1676. X      || hour > 23 || minute > 59 || second > 59)
  1677. X    return -1;
  1678. X
  1679. X  /* Mostly for convenience in sunday() macro, we use zero-origin days. */
  1680. X  dayofyear = day - 1;
  1681. X  if (month > 2 && leap(year))
  1682. X    ++dayofyear;
  1683. X  while (--month > 0)
  1684. X    dayofyear += monthlens[month - 1];
  1685. X
  1686. X  /* Wow! */
  1687. X  return 86400 * (dayofyear + 365 * (year - 1970) + nleap(year))
  1688. X    + 3600 * hour + 60 * minute + second
  1689. X#ifdef BSD
  1690. X    - correction(dayofyear,&tz)
  1691. X#else
  1692. X    - correction()
  1693. X#endif
  1694. X    ;
  1695. X}
  1696. END_OF_FILE
  1697. if test 11397 -ne `wc -c <'unctime.y'`; then
  1698.     echo shar: \"'unctime.y'\" unpacked with wrong size!
  1699. fi
  1700. # end of 'unctime.y'
  1701. fi
  1702. if test -f 'uucp.c' -a "${1}" != "-c" ; then 
  1703.   echo shar: Will not clobber existing file \"'uucp.c'\"
  1704. else
  1705. echo shar: Extracting \"'uucp.c'\" \(3117 characters\)
  1706. sed "s/^X//" >'uucp.c' <<'END_OF_FILE'
  1707. X/* $Header: uucp.c,v 2.1 89/06/09 12:25:44 network Exp $
  1708. X *
  1709. X * Handle mail destined for other hosts via UUCP.
  1710. X * Deliver is intended as a very low-level program, so we don't
  1711. X * do anything fancy here.  We just hand the message to uux.
  1712. X *
  1713. X * $Log:    uucp.c,v $
  1714. X * Revision 2.1  89/06/09  12:25:44  network
  1715. X * Update RCS revisions.
  1716. X * 
  1717. X * Revision 1.5  89/06/09  12:24:02  network
  1718. X * Baseline for 2.0 release.
  1719. X * 
  1720. X */
  1721. X
  1722. X#include "deliver.h"
  1723. X#include <sys/stat.h>
  1724. X
  1725. X/*
  1726. X * Local functions.
  1727. X */
  1728. X
  1729. Xstatic  int     uucp_copy();
  1730. X
  1731. X/*----------------------------------------------------------------------
  1732. X * Send mail to UUCP addresses (if any).
  1733. X * This is a simple implementation: invoke uux once per address.
  1734. X */
  1735. X
  1736. Xuucp_deliver()
  1737. X{
  1738. X    struct stat st;
  1739. X    DEST    *d;
  1740. X    char    *uux;
  1741. X    static char uux1[] = "/bin/uux";
  1742. X    static char uux2[] = "/usr/bin/uux";
  1743. X
  1744. X    if (stat(uux1, &st) == 0)
  1745. X        uux = uux1;
  1746. X    else if (stat(uux2, &st) == 0)
  1747. X        uux = uux2;
  1748. X    else
  1749. X    {
  1750. X        error("can't find uux!?\n");
  1751. X        return;
  1752. X    }
  1753. X
  1754. X    for (d = first_dest(); d; d = next_dest(d))
  1755. X    {
  1756. X        FILE    *uux_fp;
  1757. X        char    *bang;
  1758. X        char    *av[5];
  1759. X        char    rmail[40];
  1760. X        char    who[BUFSIZ];
  1761. X
  1762. X        if (d->d_class != CL_UUCP || d->d_state != ST_WORKING)
  1763. X            continue;
  1764. X
  1765. X        if (printaddrs)
  1766. X            (void) printf("%s\n", d->d_name);
  1767. X
  1768. X        if (dryrun)
  1769. X        {
  1770. X            d->d_state = ST_DONE;
  1771. X            continue;
  1772. X        }
  1773. X
  1774. X        bang = strchr(d->d_name, '!');
  1775. X        *bang = 0;
  1776. X        (void) sprintf(rmail, "%s!rmail", d->d_name);
  1777. X        *bang++ = '!';
  1778. X        (void) sprintf(who, "(%s)", bang);
  1779. X
  1780. X        av[0] = "uux";
  1781. X        av[1] = "-";
  1782. X        av[2] = rmail;
  1783. X        av[3] = who;
  1784. X        av[4] = NULL;
  1785. X        if ((uux_fp = ct_popenv(eff_ct, uux, av, "w")) == NULL)
  1786. X            continue;
  1787. X
  1788. X        if (uucp_copy(uux_fp) < 0)
  1789. X            dest_err(d, E_UUX);
  1790. X
  1791. X        if (ct_pclose(uux_fp))
  1792. X        {
  1793. X            /* "No such host" overrides piping problems. */
  1794. X            dest_err(d, E_NSHOST);
  1795. X        }
  1796. X        else
  1797. X            d->d_state = ST_DONE;
  1798. X    }
  1799. X}
  1800. X
  1801. X/*----------------------------------------------------------------------
  1802. X * Write the message for UUCP transmission to the given file.
  1803. X */
  1804. X
  1805. Xstatic int
  1806. Xuucp_copy(ofp)
  1807. XFILE    *ofp;
  1808. X{
  1809. X    FILE    *ifp;
  1810. X    char    *p;
  1811. X    register int c;
  1812. X    int     fd;
  1813. X    char    buf[BUFSIZ];
  1814. X
  1815. X    if ((fd = dup(tfd[T_HDR])) == -1)
  1816. X    {
  1817. X        syserr("can't dup header fd");
  1818. X        return -1;
  1819. X    }
  1820. X    (void) lseek(fd, 0L, 0);
  1821. X    if ((ifp = fdopen(fd, "r")) == NULL)
  1822. X    {
  1823. X        error("can't fdopen header fd");
  1824. X        return -1;
  1825. X    }
  1826. X
  1827. X    /*
  1828. X     * Copy the header, but tack "remote from" onto the end of the
  1829. X     * From_ line.  (If it weren't for dealing with the From_ line,
  1830. X     * I'd skip stream I/O altogether and use read/write.  Maybe
  1831. X     * I should save the length of the From_ line when I copy it...)
  1832. X     */
  1833. X
  1834. X    (void) fgets(buf, GETSIZE(buf), ifp);
  1835. X    if ((p = strchr(buf, '\n')) != NULL)
  1836. X        *p = 0;
  1837. X    (void) fprintf(ofp, "%s remote from %s\n", buf, hostname);
  1838. X
  1839. X    while ((c = getc(ifp)) != EOF)
  1840. X        (void) putc(c, ofp);
  1841. X
  1842. X    (void) fclose(ifp);
  1843. X
  1844. X    /*
  1845. X     * Copy the body
  1846. X     */
  1847. X
  1848. X    if ((fd = dup(tfd[T_BODY])) == -1)
  1849. X    {
  1850. X        syserr("can't dup body fd");
  1851. X        return -1;
  1852. X    }
  1853. X    (void) lseek(fd, 0L, 0);
  1854. X    if ((ifp = fdopen(fd, "r")) == NULL)
  1855. X    {
  1856. X        error("can't fdopen body fd");
  1857. X        (void) close(fd);
  1858. X        return -1;
  1859. X    }
  1860. X
  1861. X    while ((c = getc(ifp)) != EOF)
  1862. X        (void) putc(c, ofp);
  1863. X
  1864. X    (void) fclose(ifp);
  1865. X    return 0;
  1866. X}
  1867. END_OF_FILE
  1868. if test 3117 -ne `wc -c <'uucp.c'`; then
  1869.     echo shar: \"'uucp.c'\" unpacked with wrong size!
  1870. fi
  1871. # end of 'uucp.c'
  1872. fi
  1873. echo shar: End of shell archive.
  1874. exit 0
  1875.  
  1876.  
  1877.